using Godot;
using System;

namespace CurrentGame.GUI.PlaceGrid;


public partial class GridSelector : Node2D
{

    [Export]
    public bool Activated { get; set; } = false;

    // Public members
    public Vector2 TargetLocalPosition { get; private set; } = Vector2.Zero;

    // Private members
    private Vector2I _cameraRawSize;
    private Vector2I _mapXRange, _mapYRange;
    private int _onLeftGround = 0, _onRightGround = 0, _haveSpace = 0;

    // Node references
    private Viewport _viewport;
    private PlaceModeGrid _grid;
    private CinematicCamera _camera;

    // GODOT - Callbacks
    public override void _Ready()
    {
        _viewport = GetViewport();
        _grid = GetNode<PlaceModeGrid>("..");
        _camera = _grid.GameCamera;
        _cameraRawSize = _grid.GameCamera.CameraRawSize;
        _mapXRange = new Vector2I(_grid.LeftTopCoordinate.X, _grid.RightBottomCoordinate.X);
        _mapYRange = new Vector2I(_grid.LeftTopCoordinate.Y, _grid.RightBottomCoordinate.Y);
    }

    public override void _PhysicsProcess(double delta)
    {
        if (!Activated) { return; }

        var cameraSize = _camera.GetCurrentCameraSize();
        var mousePosition = (Vector2I)_viewport.GetMousePosition();
        mousePosition = new Vector2I(
            Mathf.Clamp(mousePosition.X, 0, _cameraRawSize.X),
            Mathf.Clamp(mousePosition.Y, 0, _cameraRawSize.Y));
        var viewPosition = new Vector2(
            (float)mousePosition.X / _cameraRawSize.X * cameraSize.X,
            (float)mousePosition.Y / _cameraRawSize.Y * cameraSize.Y);
        viewPosition -= (Vector2)cameraSize * 0.5f;
        var worldPosition = viewPosition + _camera.GlobalPosition;
        var localPosition = _grid.ToLocal(worldPosition);
        var mapPosition = _grid.LocalToMap(localPosition);
        mapPosition = new Vector2I(
            Mathf.Clamp(mapPosition.X, _mapXRange.X, _mapXRange.Y),
            Mathf.Clamp(mapPosition.Y, _mapYRange.X, _mapYRange.Y));

        localPosition = new Vector2(
            _grid.GridSize * mapPosition.X + _grid.GridSize,
            _grid.GridSize * mapPosition.Y + _grid.GridSize);

        Position = localPosition;
        TargetLocalPosition = localPosition;

        _grid.NotifySelectionChange(mapPosition, _grid.ToGlobal(localPosition));
    }

    // Export interfaces
    public bool CheckAvailable()
    {
        return _onLeftGround > 0 && _onRightGround > 0 && _haveSpace <= 0;
    }

    // GODOT - Signals
    // Main area check
    private void Signal_MainNodeEnter(Node area)
    {
        ++_haveSpace;
    }
    private void Singal_MainNodeLeave(Node area)
    {
        --_haveSpace;
    }

    // Left bottom area check
    private void Signal_LeftNodeEnter(Node area)
    {
        ++_onLeftGround;
    }
    private void Signal_LeftNodeLeave(Node area)
    {
        --_onLeftGround;
    }

    // Right bottom area check
    private void Signal_RightNodeEnter(Node area)
    {
        ++_onRightGround;
    }
    private void Signal_RightNodeLeave(Node area)
    {
        --_onRightGround;
    }

}
